﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;
using com.IronOne.BoardPACWinApp.Common;
using com.IronOne.BoardPACWinApp.Helpers;
using com.IronOne.BoardPACWinApp.Sync;
using com.IronOne.BoardPACWinApp.View.UserControl;
using com.IronOne.BoardPACWinAppBO.Auth;
using com.IronOne.BoardPACWinAppBO.General;
using com.IronOne.BoardPACWinAppService.Auth;
using com.IronOne.BoardPACWinAppService.Init;
using com.IronOne.BoardPACWinAppUtil.Enums;
using com.IronOne.BoardPACWinAppUtil.Security;
using com.IronOne.BoardPACWinAppUtil.Util;
using GalaSoft.MvvmLight.Messaging;

// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234237

namespace com.IronOne.BoardPACWinApp.View.Page
{
    /// <summary>
    ///     A basic page that provides characteristics common to most applications.
    /// </summary>
    public sealed partial class LoginPage
    {
        private int _deviceRegStatus;
        private bool _isFirstTimeSvrValue;
        private bool _isNotRegisterdOffline;
        private bool _isNotRegisterdOnline = true;
        private bool _isPendingOffline;
        private bool _isPendingOnline = true;
        private bool _isSsessionExpired;
        private bool _isSync;
        private readonly IAuthService _authService;
        private readonly IDialogService _dialogService;
        private readonly IInitService _initService;
        private readonly INavigationService _navigationService;

        public LoginPage()
        {
            InitializeComponent();
            NavigationHelper = new NavigationHelper(this);

            _navigationService = new NavigationService();
            _dialogService = new DialogService();
            _authService = new AuthService();
            _initService = new InitService();
        }

        /// <summary>
        ///     NavigationHelper is used on each page to aid in navigation and
        ///     process lifetime management
        /// </summary>
        public NavigationHelper NavigationHelper { get; private set; }

        protected override async void HandleMessages(NotificationMessage<MessageDataModel> mdm)
        {
            try
            {
                base.HandleMessages(mdm);

                if (mdm.Notification.Equals(MessageCodes.SYNC_DATA_DOWNLOAD_SUCCESS))
                {
                    if (!_isSync) return;
                    _isSync = false;

                    if (_isFirstTimeSvrValue)
                    {
                        var isForcedPasswordChange =
                            await
                                _authService.GetSettingValueBySettingName(DatabaseType.UserDb,
                                    ApplicationConstants.UserDbSettingNames.ForcePasswordChange);
                        if (Convert.ToInt32(isForcedPasswordChange) != 1) // 1 == True
                        {
                            _navigationService.NavigateTo(typeof(MeetingsPage));
                            return;
                        }

                        await ChangePasswordUiManip();
                        return;
                    }

                    _navigationService.NavigateTo(typeof(MeetingsPage));
                    return;
                }

                if (mdm.Notification.Equals(MessageCodes.SYNC_ERROR_STOP) ||
                    mdm.Notification.Equals(MessageCodes.SYNC_DATA_DOWNLOAD_FAIL))
                {
                    if (!_isSync) return;

                    LblLoginHeader.Text = "sync failed!!!";
                    LblLoginSubHeader.Text = "your first sync encountered an error";
                    BtnLogin.Content = "Retry";
                    BtnLogin.Visibility = Visibility.Visible;
                    PgbLogin.Visibility = Visibility.Collapsed;
                }

                if (mdm.Notification.Equals(MessageCodes.IS_ONLINE))
                {
                    var isOnline = (bool)mdm.Content.MessageData;

                    if (isOnline)
                    {
                        //NOTE: Remove go online panel
                        if(!Global.UserForceWentOffline)
                            GoOnlinePanel.Visibility = Visibility.Collapsed;

                        if (_deviceRegStatus == (int)DeviceStatus.Pending && _isPendingOffline)
                        {
                            _isPendingOffline = false;
                            _isPendingOnline = true;
                            PendingOnline();
                        }

                        if (_deviceRegStatus == (int)DeviceStatus.NotRegisterd && _isNotRegisterdOffline)
                        {
                            _isNotRegisterdOffline = false;
                            _isNotRegisterdOnline = true;
                            NotRegisterdOnline();
                        }
                    }
                    else //Offline
                    {
                        //NOTE: Now user will have a button to force try online
                        GoOnlinePanel.Visibility = Visibility.Visible;
                        LblLoginSubHeader.Text = "you're offline at the moment";

                        if (_deviceRegStatus == (int)DeviceStatus.Pending && _isPendingOnline)
                        {
                            _isPendingOffline = true;
                            _isPendingOnline = false;
                            PendingOffline();
                        }

                        if (_deviceRegStatus == (int)DeviceStatus.NotRegisterd && _isNotRegisterdOnline)
                        {
                            _isNotRegisterdOffline = true;
                            _isNotRegisterdOnline = false;
                            NotRegisterdOffline();
                        }
                    }
                }
            }
            catch (Exception)
            {
                LblLoginHeader.Text = "general error!";
                LblLoginSubHeader.Text = "process encountered an error";
                BtnLogin.Content = "Retry";
                BtnLogin.Visibility = Visibility.Visible;
                PgbLogin.Visibility = Visibility.Collapsed;
            }
        }

        /// <summary>
        ///     Populates the page with content passed during navigation.  Any saved state is also
        ///     provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="navigationParameter">
        ///     The parameter value passed to
        ///     <see cref="Frame.Navigate(Type, Object)" /> when this page was initially requested.
        /// </param>
        /// <param name="pageState">
        ///     A dictionary of state preserved by this page during an earlier
        ///     session.  This will be null the first time a page is visited.
        /// </param>
        /// btn_Login_Click
        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
        }

        /// <summary>
        ///     Preserves state associated with this page in case the application is suspended or the
        ///     page is discarded from the navigation cache.  Values must conform to the serialization
        ///     requirements of <see cref="SuspensionManager.SessionState" />.
        /// </summary>
        /// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
        protected override void SaveState(Dictionary<String, Object> pageState)
        {
        }

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            var isException = false;
            try
            {
                base.OnNavigatedTo(e);
                NavigationHelper.OnNavigatedTo(e);
                ChangePasswordPanel.Visibility = Visibility.Collapsed;

                #region Commented

                //Hide change password panel initially
                //----------------------------------------------------------------------------------
                //double val = ChangePasswordPanel.ActualWidth;
                //Storyboard storyboard = new Storyboard();
                //Duration duration = new Duration(TimeSpan.FromMilliseconds(animeTime));
                //CubicEase ease = new CubicEase { EasingMode = EasingMode.EaseOut };

                //DoubleAnimation animation = new DoubleAnimation();
                //animation.EasingFunction = ease;
                //animation.Duration = duration;
                //storyboard.Children.Add(animation);
                //animation.From = val;
                //animation.To = 0;
                //animation.EnableDependentAnimation = true;
                //Storyboard.SetTarget(animation, ChangePasswordPanel);
                //Storyboard.SetTargetProperty(animation, "(ColumnDefinition.MaxWidth)");
                //storyboard.Begin();
                //---------------------------------------------------------------------------------- 

                #endregion

                _isSync = false;
                SyncManager.StopSync();

                //NOTE: If Err110 comes in a parameter that mean session expiration, so
                //after the login user will be naigated back to where the user was before.
                //Username will be readonly and user can goto normal login as well.
                var msg = e.Parameter as string;
                if (!String.IsNullOrWhiteSpace(msg) && msg.Equals(ErrorCode.Err110))
                {
                    _isSsessionExpired = true;
                    SessionExpired();

                    _deviceRegStatus = (int)DeviceStatus.Active;
                    await
                        ProvideDataContextAndSupportInfo(new LogOnModel
                        {
                            Differlogin = Visibility.Visible
                        });
                    return;
                }

                Global.CleanUp();
                MeetingsPage.IsOneTime = true;

                var devModel = await _authService.GetDeviceAuthStatus();
                _deviceRegStatus = devModel.DeviceRegistrationStatus;

                if (_deviceRegStatus == (int)DeviceStatus.Wipeout)
                {
                    _navigationService.NavigateTo(typeof(WipedOutPage));
                    return;
                }

                if (_deviceRegStatus == (int)DeviceStatus.Pending)
                {
                    #region Pending Offline

                    if (!Global.IsOnline) //Offline
                    {
                        PendingOffline();
                    }

                    #endregion

                    #region Pending Online

                    if (Global.IsOnline) //Online
                    {
                        PendingOnline();
                    }

                    GrdMemberUsername.Visibility = Visibility.Collapsed;
                    GrdAdminUsername.Visibility = Visibility.Collapsed;
                    GrdAdminPassword.Visibility = Visibility.Collapsed;
                    PgbLogin.Visibility = Visibility.Visible;
                    TglLoginSwitch.Visibility = Visibility.Collapsed;
                    LblLoginSwitchLable.Visibility = Visibility.Collapsed;
                    BtnLogin.Visibility = Visibility.Collapsed;

                    #endregion
                }

                if (_deviceRegStatus == (int)DeviceStatus.NotRegisterd)
                {
                    #region NotRegisterd Offline

                    if (!Global.IsOnline) //Offline
                    {
                        NotRegisterdOffline();
                    }

                    #endregion

                    #region NotRegisterd Online

                    if (Global.IsOnline) //Online
                    {
                        NotRegisterdOnline();
                    }

                    #endregion
                }

                //Registerd and Offline
                if (_deviceRegStatus == (int)DeviceStatus.Active && !Global.IsOnline)
                {
                    LblLoginSubHeader.Visibility = Visibility.Visible;
                    LblLoginSubHeader.Text = "you're offline at the moment";
                    LblLoginSubHeader.Margin = new Thickness(0, 15, 0, 40);
                    LblLoginHeader.Margin = new Thickness(0, 0, 0, 0);

                    GoOnlinePanel.Visibility = Visibility.Visible;
                }

                await ProvideDataContextAndSupportInfo(new LogOnModel());
            }
            catch (Exception)
            {
                isException = true;
            }
            if (isException)
                await _dialogService.ShowMessage("General error encountered");
        }

        private async Task ProvideDataContextAndSupportInfo(LogOnModel model)
        {
            try
            {
                DataContext = model;
                var mod = await _authService.GetSupportInfoFromDb();
                mod.ShowSupportInfoUi = mod.ShowSupportInfo ? Visibility.Visible : Visibility.Collapsed;
                GrdSupport.DataContext = mod;
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void SessionExpired()
        {
            try
            {
                LblLoginHeader.Text = "session out!";
                LblLoginHeader.Margin = new Thickness(0, 0, 0, 0);
                LblLoginSubHeader.Visibility = Visibility.Visible;
                LblLoginSubHeader.Text =
                    "your current session is expired, please provide credentials to continue";
                PgbLogin.Visibility = Visibility.Collapsed;
                BtnLogin.Visibility = Visibility.Visible;

                if (!Global.IsOnline || Global.UserForceWentOffline)
                {
                    GoOnlinePanel.Visibility = Visibility.Visible;
                }

                BasePage.CleanupPartial();
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void PendingOnline()
        {
            try
            {
                LblLoginHeader.Text = "please wait...";
                LblLoginHeader.Margin = new Thickness(0, 0, 0, 0);
                LblLoginSubHeader.Visibility = Visibility.Visible;
                LblLoginSubHeader.Text = "your authorization request is pending";
                PgbLogin.Visibility = Visibility.Visible;
                BtnLogin.Visibility = Visibility.Collapsed;

                PollForDeviceAuth();
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void PendingOffline()
        {
            try
            {
                _isPendingOffline = true;
                _isPendingOnline = false;
                LblLoginHeader.Text = "please wait...";
                LblLoginHeader.Margin = new Thickness(0, 0, 0, 0);
                LblLoginSubHeader.Visibility = Visibility.Visible;
                LblLoginSubHeader.Text = "authorization halted due to offline, wait till we get back online";
                BtnLogin.Visibility = Visibility.Collapsed;
                PgbLogin.Visibility = Visibility.Visible;
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void NotRegisterdOnline()
        {
            try
            {
                TglLoginSwitch.Visibility = Visibility.Visible;
                LblLoginSwitchLable.Visibility = Visibility.Visible;
                GrdMemberUsername.Visibility = Visibility.Visible;
                TxtMemberUsername.PlaceholderText = "Member username";
                TxtMemberUsername.Focus(FocusState.Keyboard);

                TxtAdminUsername.PlaceholderText = "Admin username";
                GrdAdminUsername.Visibility = Visibility.Visible;
                TxtAdminPassword.PlaceholderText = "Admin pssword";
                GrdAdminPassword.Visibility = Visibility.Visible;

                LblLoginHeader.Text = "verify device";
                LblLoginHeader.Margin = new Thickness(0, 0, 0, 0);
                LblLoginSubHeader.Visibility = Visibility.Collapsed;

                PgbLogin.Visibility = Visibility.Collapsed;
                BtnLogin.Visibility = Visibility.Visible;
                BtnLogin.Content = "Authorize device";

                DecoyControl.Focus(FocusState.Programmatic);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void NotRegisterdOffline()
        {
            try
            {
                _isNotRegisterdOffline = true;
                _isNotRegisterdOnline = false;
                LblLoginHeader.Text = "please wait...";
                LblLoginHeader.Margin = new Thickness(0, 0, 0, 0);
                LblLoginSubHeader.Visibility = Visibility.Visible;
                LblLoginSubHeader.Text = "device verification halted due to offline, wait till we get back online";

                GrdMemberUsername.Visibility = Visibility.Collapsed;
                GrdAdminUsername.Visibility = Visibility.Collapsed;
                GrdAdminPassword.Visibility = Visibility.Collapsed;
                PgbLogin.Visibility = Visibility.Visible;
                TglLoginSwitch.Visibility = Visibility.Collapsed;
                LblLoginSwitchLable.Visibility = Visibility.Collapsed;
                BtnLogin.Visibility = Visibility.Collapsed;
            }
            catch (Exception)
            {
                throw;
            }
        }

        private async void PollForDeviceAuth()
        {
            try
            {
                BtnLogin.Visibility = Visibility.Collapsed;
                PgbLogin.Visibility = Visibility.Visible;

                var devId = DeviceService.GetAppSpecificHardwareId();

                while (_deviceRegStatus != (int)DeviceStatus.Active)
                {
                    var rdm = await _authService.DeviceAuthorizeStatus(devId);
                    if (rdm.IsError)
                    {
                        LblLoginHeader.Text = "verify device";

                        LblLoginSubHeader.Visibility = Visibility.Visible;
                        LblLoginSubHeader.Text = rdm.ErrorMessage;

                        BtnLogin.Content = "Retry";
                        BtnLogin.Visibility = Visibility.Visible;
                        PgbLogin.Visibility = Visibility.Collapsed;

                        _deviceRegStatus = (int)DeviceStatus.Pending;
                        break;
                    }

                    if (Convert.ToInt32(rdm.Data) == (int)DeviceStatus.Active)
                    {
                        _deviceRegStatus = (int)DeviceStatus.Active;

                        // Update device status in DB
                        var devM = await _authService.GetDeviceAuthStatus();
                        devM.DeviceRegistrationStatus = (Convert.ToInt32(rdm.Data));
                        var result = await _authService.SetDeviceAuthStatus(devM);

                        if (result) break; //Break if the DB update is successful
                    }
                    if (Convert.ToInt32(rdm.Data) == (int)DeviceStatus.Rejected)
                    {
                        _deviceRegStatus = (int)DeviceStatus.NotRegisterd;
                        await
                            _dialogService.ShowMessage(
                                "Your authorization request has been denied by the administrator.");
                        _navigationService.NavigateTo(typeof(SplashPage));
                        break;
                    }
                    await Task.Delay(2000);
                }

                if (_deviceRegStatus == (int)DeviceStatus.Active)
                {
                    //Because init() has been skipped due to not registerd state.
                    //So after been registerd this code will do the init and come back to login
                    _navigationService.NavigateTo(typeof(SplashPage));
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void tgl_LoginSwitch_Toggled(object sender, RoutedEventArgs e)
        {
            try
            {
                //Suren: This code has to be here, I don't know why :(
                if (GrdMemberUsername == null)
                    return;

                var ts = e.OriginalSource as ToggleSwitch;
                if (ts != null && ts.IsOn)
                {
                    GrdMemberUsername.Visibility = Visibility.Visible;
                    TxtMemberUsername.PlaceholderText = "Member username";
                    TxtMemberUsername.Text = "";
                    TxtMemberUsername.Focus(FocusState.Keyboard);

                    TxtAdminUsername.Text = "";
                    TxtAdminPassword.Password = "";
                    TxtAdminUsername.PlaceholderText = "Admin username";
                    TxtAdminPassword.PlaceholderText = "Admin password";
                }
                else
                {
                    GrdMemberUsername.Visibility = Visibility.Collapsed;
                    TxtAdminUsername.Focus(FocusState.Keyboard);

                    TxtAdminUsername.Text = "";
                    TxtAdminPassword.Password = "";
                    TxtAdminUsername.PlaceholderText = "Username";
                    TxtAdminPassword.PlaceholderText = "Password";
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void txt_MemberUsername_KeyUp(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key != VirtualKey.Enter) return;

            if (!String.IsNullOrWhiteSpace(TxtMemberUsername.Text))
            {
                TxtAdminUsername.Focus(FocusState.Keyboard);
            }
        }

        private void txt_AdminUsername_KeyUp(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key != VirtualKey.Enter) return;

            if (!String.IsNullOrWhiteSpace(TxtAdminUsername.Text))
            {
                TxtAdminPassword.Focus(FocusState.Keyboard);
            }
        }

        private async void txt_AdminPassword_KeyUp(object sender, KeyRoutedEventArgs e)
        {
            try
            {
                if (e.Key != VirtualKey.Enter) return;

                DecoyControl.Focus(FocusState.Programmatic);
                BtnLogin.IsEnabled = false;
                await LoginProcess();
                BtnLogin.IsEnabled = true;
            }
            catch (Exception)
            {
            }
        }

        private async void btn_Login_Click(object sender, RoutedEventArgs e)
        {
            var isException = false;
            try
            {
                DecoyControl.Focus(FocusState.Programmatic);

                //txt_AdminUsername.Text = "tharindu";
                //txt_AdminPassword.Password = "123";

                TxtAdminUsername.IsReadOnly = true;
                BtnLogin.IsEnabled = false;
                await LoginProcess();
            }
            catch (Exception)
            {
                isException = true;
                //_dialogService.ShowMessage("Message:" + ew.Message + "\nInnerException:" + ew.InnerException + "\nStackTrace:" + ew.StackTrace);
            }
            finally
            {
                TxtAdminUsername.IsReadOnly = false;
                BtnLogin.IsEnabled = true;
            }
            if (isException)
            {
                PgbLogin.Visibility = Visibility.Collapsed;
                await _dialogService.ShowMessage("Login general error encountered");
            }
        }

        private async Task LoginProcess()
        {
            try
            {
                if (_isSync)
                {
                    LoginEndExecution();
                    return;
                }

                if (_deviceRegStatus == (int)DeviceStatus.Pending)
                {
                    PollForDeviceAuth();
                    return;
                }

                var logOnModel = (LogOnModel)DataContext;

                //Online & NotRegisterd
                if (Global.IsOnline && _deviceRegStatus == (int)DeviceStatus.NotRegisterd)
                {
                    #region Online & NotRegisterd

                    if (TglLoginSwitch.IsOn) //Admin On
                    {
                        #region Admin On

                        if ((String.IsNullOrWhiteSpace(logOnModel.MemberUserName)) &&
                            (String.IsNullOrWhiteSpace(logOnModel.UserName)) &&
                            (String.IsNullOrWhiteSpace(logOnModel.Password)))
                        {
                            await _dialogService.ShowMessage("Member and admin credentials cannot be empty");
                            TxtMemberUsername.Focus(FocusState.Keyboard);
                            return;
                        }
                        if (String.IsNullOrWhiteSpace(logOnModel.MemberUserName))
                        {
                            await _dialogService.ShowMessage("Member username cannot be empty");
                            TxtMemberUsername.Focus(FocusState.Keyboard);
                            return;
                        }
                        if ((String.IsNullOrWhiteSpace(logOnModel.UserName)) &&
                            (String.IsNullOrWhiteSpace(logOnModel.Password)))
                        {
                            await _dialogService.ShowMessage("Admin credentials cannot be empty");
                            TxtAdminUsername.Focus(FocusState.Keyboard);
                            return;
                        }
                        if (String.IsNullOrWhiteSpace(logOnModel.UserName))
                        {
                            await _dialogService.ShowMessage("Admin username cannot be empty");
                            TxtAdminUsername.Focus(FocusState.Keyboard);
                            return;
                        }
                        if (String.IsNullOrWhiteSpace(logOnModel.Password))
                        {
                            await _dialogService.ShowMessage("Admin password cannot be empty");
                            TxtAdminPassword.Focus(FocusState.Keyboard);
                            return;
                        }

                        #endregion
                    }

                    if (!TglLoginSwitch.IsOn) //Admin Off
                    {
                        #region Admin Off

                        if ((String.IsNullOrWhiteSpace(logOnModel.UserName)) &&
                            (String.IsNullOrWhiteSpace(logOnModel.Password)))
                        {
                            await _dialogService.ShowMessage("User credentials cannot be empty");
                            TxtAdminUsername.Focus(FocusState.Keyboard);
                            return;
                        }
                        if (String.IsNullOrWhiteSpace(logOnModel.UserName))
                        {
                            await _dialogService.ShowMessage("Username cannot be empty");
                            TxtAdminUsername.Focus(FocusState.Keyboard);
                            return;
                        }
                        if (String.IsNullOrWhiteSpace(logOnModel.Password))
                        {
                            await _dialogService.ShowMessage("Password cannot be empty");
                            TxtAdminPassword.Focus(FocusState.Keyboard);
                            return;
                        }

                        #endregion
                    }

                    BtnLogin.IsEnabled = false;
                    TxtMemberUsername.IsEnabled = false;
                    TxtAdminUsername.IsEnabled = false;
                    TxtAdminPassword.IsEnabled = false;

                    logOnModel.DeviceId = DeviceService.GetAppSpecificHardwareId();
                    var devModel = await _authService.AuthorizeDevice(logOnModel);
                    if (devModel.IsError)
                    {
                        //display error and retry
                        BtnLogin.IsEnabled = true;
                        TxtMemberUsername.IsEnabled = true;
                        TxtAdminUsername.IsEnabled = true;
                        TxtAdminPassword.IsEnabled = true;
                        await _dialogService.ShowMessage(devModel.ErrorMessage);
                    }
                    else
                    {
                        //Open the same page again
                        _navigationService.NavigateTo(typeof(LoginPage));
                    }

                    #endregion

                    return;
                }

                if (!Global.IsOnline && _deviceRegStatus == (int)DeviceStatus.NotRegisterd)
                {
                    #region Offline & NotRegisterd

                    NotRegisterdOffline();

                    #endregion

                    return;
                }

                //Online & Registerd
                if (Global.IsOnline && _deviceRegStatus == (int)DeviceStatus.Active)
                {
                    #region Online & Registerd

                    var validate = await LoginTextboxValidations(logOnModel);
                    if (!validate) return;

                    PgbLogin.Visibility = Visibility.Visible;

                    ResponseDataModel rdm;
                    if (Global.UserForceWentOffline)
                    {
                        await OfflineLogin(logOnModel);
                        return;
                    }
                    else
                        rdm = await _authService.LogOn(logOnModel);

                    if (rdm.IsError)
                    {
                        PgbLogin.Visibility = Visibility.Collapsed;

                        if (rdm.ErrorMessage.ToLower().Equals(ResourceHandler.Get("err_102").ToLower()))
                        {
                            var res =
                                await
                                    _dialogService.ShowMessageYesNo(
                                        rdm.ErrorMessage + "\nWould you like to login offline?",
                                        DefaultButtonCommand.Yes);
                            if (res) await OfflineLogin(logOnModel);
                            return;
                        }

                        await _dialogService.ShowMessage(rdm.ErrorMessage);
                        return;
                    }

                    var asm = await _initService.ReadAppSettingsFromDb();
                    var minWebVersion = int.Parse(asm.MinWebVersion.Replace(".", "").Trim());
                    var currentWebVersion = int.Parse(rdm.WebAppVersion.Replace(".", "").Trim());
                    //asm.CurrentWebVersion
                    if (!(currentWebVersion >= minWebVersion))
                    {
                        PgbLogin.Visibility = Visibility.Collapsed;
                        await
                            _dialogService.ShowMessage(
                                "You are connecting to a older version of the BoardPAC web. Please contact your administrator.\n" +
                                "Current web version: " + rdm.WebAppVersion + "\nMinimum supported web version: " +
                                asm.MinWebVersion);
                        return;
                    }

                    var usrModel = (UserModel)rdm.Data;
                    Global.UserId = usrModel.UserId;
                    Global.IsFirstTime = usrModel.InitialLogin;

                    //If user db deleted this will identify that db is created again
                    //for the first time, so sync on the login page will initiate
                    if (!usrModel.InitialLogin)
                    {
                        Global.IsFirstTime = ((UserModel)rdm.Data).IsFirstTimeCheck;
                    }

                    //This is the server value. This val used in handle msg
                    //If this is true only change password appear after the initial sync.
                    _isFirstTimeSvrValue = usrModel.InitialLogin;

                    Global.Password = TxtAdminPassword.Password;
                    Global.Username = TxtAdminUsername.Text;

                    //Initial password change is done in handle message, its going to execute after the sync finishes.

                    var isForcedPasswordChange =
                        await
                            _authService.GetSettingValueBySettingName(DatabaseType.UserDb,
                                ApplicationConstants.UserDbSettingNames.ForcePasswordChange);

                    //if (Convert.ToInt32(isForcedPasswordChange) == 1) // 1 == True
                    //if (!Global.IsFirstTime)
                    //{

                    if (isForcedPasswordChange != null && Convert.ToInt32(isForcedPasswordChange) == 1 &&
                        usrModel.ResetPassword)
                    {
                        await ChangePasswordUiManip();
                        await _dialogService.ShowMessage("Please change your password before proceed.");
                        return;
                    }

                    if (!Global.IsFirstTime && usrModel.PasswordExpired)
                    {
                        await ChangePasswordUiManip();
                        await _dialogService.ShowMessage(usrModel.PasswordExpiredMessage);
                        return;
                    }

                    //Display the message comes in this tag as a warning to the user
                    if (!Global.IsFirstTime && !String.IsNullOrWhiteSpace(usrModel.PasswordExpiredMessage))
                    {
                        var resp =
                            await
                                _dialogService.ShowMessageYesNo(
                                    usrModel.PasswordExpiredMessage + "\nWould you like to change your password now?",
                                    DefaultButtonCommand.No);
                        if (resp)
                        {
                            await ChangePasswordUiManip();
                            return;
                        }
                    }

                    LoginEndExecution();

                    #endregion

                    return;
                }

                //Offline & Registerd
                if (!Global.IsOnline && _deviceRegStatus == (int)DeviceStatus.Active)
                {
                    await OfflineLogin(logOnModel);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private async Task<bool> LoginTextboxValidations(LogOnModel logOnModel)
        {
            try
            {
                if (String.IsNullOrWhiteSpace(logOnModel.UserName) &&
                    (String.IsNullOrWhiteSpace(logOnModel.Password)))
                {
                    await _dialogService.ShowMessage("Username and password cannot be empty");
                    TxtAdminUsername.Focus(FocusState.Keyboard);
                    return false;
                }
                if (String.IsNullOrWhiteSpace(logOnModel.UserName))
                {
                    await _dialogService.ShowMessage("Username cannot be empty");
                    TxtAdminUsername.Focus(FocusState.Keyboard);
                    return false;
                }
                if (!String.IsNullOrWhiteSpace(logOnModel.Password)) return true;
                await _dialogService.ShowMessage("Password cannot be empty");
                TxtAdminPassword.Focus(FocusState.Keyboard);
                return false;
            }
            catch (Exception)
            {
                throw;
            }
        }

        private async Task OfflineLogin(LogOnModel logOnModel)
        {
            #region Offline & Registerd

            try
            {
                var validate = await LoginTextboxValidations(logOnModel);
                if (!validate) return;

                PgbLogin.Visibility = Visibility.Visible;
                BtnLogin.IsEnabled = false;

                var rdm = await _authService.LogOnOffline(logOnModel);
                if (!rdm.IsError)
                {
                    Global.UserId = Convert.ToInt32(rdm.Data);
                    //Offline success means its not the first time
                    Global.IsFirstTime = false;
                    Global.Password = TxtAdminPassword.Password;
                    Global.Username = TxtAdminUsername.Text;

                    _isSync = false;
                    Global.UserForceWentOffline = true;

                    if (_isSsessionExpired)
                    {
                        _navigationService.GoBack(Frame);
                        return;
                    }

                    //NOTE: Login progressbar need to collapsed after this moment. Otherwise
                    //it will still display even below message pops up.
                    PgbLogin.Visibility = Visibility.Collapsed;

                    #region App offline usage check
                    int lastofflineConsecutiveLimiti = 0;
                    var offlineUsageCheck = await _authService.GetSettingValueBySettingName(DatabaseType.UserDb, ApplicationConstants.UserDbSettingNames.AppOfflineUsageCheck);
                    if (offlineUsageCheck != null && offlineUsageCheck.ToString().Equals("1"))
                    {
                        var enforceOnlineLoginDuration = await _authService.GetSettingValueBySettingName(DatabaseType.UserDb, ApplicationConstants.UserDbSettingNames.EnforceOnlineLoginDuration);
                        var lastEnforceOnlineLogin = await _authService.GetSettingUsageValueBySettingName(ApplicationConstants.UserDbSettingNames.EnforceOnlineLoginDuration);
                        DateTime dt = Convert.ToDateTime(lastEnforceOnlineLogin);
                        int dur = Convert.ToInt32(enforceOnlineLoginDuration);
                        if (DateTime.Now.Subtract(dt).TotalDays >= dur)
                        {
                            await _dialogService.ShowMessage("EnforceOnlineLoginDuration");
                            return;
                        }

                        var offlineConsecutiveLimit = await _authService.GetSettingValueBySettingName(DatabaseType.UserDb, ApplicationConstants.UserDbSettingNames.OfflineConsecutiveLimit);
                        var lastofflineConsecutiveLimit = await _authService.GetSettingUsageValueBySettingName(ApplicationConstants.UserDbSettingNames.OfflineConsecutiveLimit);
                        if (lastofflineConsecutiveLimit == null)
                            lastofflineConsecutiveLimiti = 1;
                        else
                        {
                            lastofflineConsecutiveLimiti = Convert.ToInt32(lastofflineConsecutiveLimit);
                            lastofflineConsecutiveLimiti++;
                        }

                        int offlineConsecutiveLimiti = Convert.ToInt32(offlineConsecutiveLimit);
                        int diff = offlineConsecutiveLimiti - lastofflineConsecutiveLimiti;
                        if (diff < 0)
                        {
                            bool resp = await _dialogService.ShowMessageYesNo("You have no offline login attempts left.\nWould you like to go online?", DefaultButtonCommand.Yes);
                            if (resp)
                            {
                                await GoOnlineCommon();
                            }
                            return;
                        }
                        if (diff == 0)
                        {
                            bool res = await _dialogService.ShowMessageYesNo("This is your last offline login attempt.\nWould you like to go online?", DefaultButtonCommand.Yes);
                            if (res)
                            {
                                await GoOnlineCommon();
                                return;
                            }
                        }
                        if (diff <= 3 && diff > 0)
                        {
                            string attem = (diff == 1) ? "attempt" : "attempts";
                            await _dialogService.ShowMessage("You have " + diff + " more offline login " + attem + " left");
                        }
                    }
                    #endregion

                    await _authService.SetSettingUsageValueBySettingName(ApplicationConstants.UserDbSettingNames.OfflineConsecutiveLimit, lastofflineConsecutiveLimiti.ToString());
                    _navigationService.NavigateTo(typeof(MeetingsPage));
                    return;
                }
                if (rdm.IsError)
                {
                    PgbLogin.Visibility = Visibility.Collapsed;

                    await _dialogService.ShowMessage(rdm.ErrorMessage);

                    if (rdm.ErrorCode.Equals("0")) //0: Means user not avilable in database
                        TxtAdminUsername.Focus(FocusState.Keyboard);

                    if (rdm.ErrorCode.Equals("1")) //1: Means password is incorrect
                        TxtAdminPassword.Focus(FocusState.Keyboard);
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                PgbLogin.Visibility = Visibility.Collapsed;
                BtnLogin.IsEnabled = true;
            }

            #endregion
        }

        private void LoginEndExecution()
        {
            try
            {
                //_authService.CloseAllConnections();
                SyncManager.GetInstance().StartSync();

                if (Global.IsFirstTime)
                {
                    ChangePasswordPanel.Visibility = Visibility.Collapsed;
                    _isSync = true;
                    //Navigating to MeetingsPage after the first sync will be done by message receiver
                    //LblLoginHeader.Text = "synchronizing";
                    LblLoginHeader.Text = "please wait";
                    LblLoginHeader.Margin = new Thickness(0, 0, 0, 0);
                    LblLoginSubHeader.Visibility = Visibility.Visible;
                    //LblLoginSubHeader.Text = "your first sync may take a moment";
                    LblLoginSubHeader.Text = "we're getting few things ready on your device";

                    GrdMemberUsername.Visibility = Visibility.Collapsed;
                    GrdAdminUsername.Visibility = Visibility.Collapsed;
                    GrdAdminPassword.Visibility = Visibility.Collapsed;
                    PgbLogin.Visibility = Visibility.Visible;
                    TglLoginSwitch.Visibility = Visibility.Collapsed;
                    LblLoginSwitchLable.Visibility = Visibility.Collapsed;
                    BtnLogin.Visibility = Visibility.Collapsed;
                }
                else if (GeneralSettingsFlyout.IsFirstTime)
                {
                    ChangePasswordPanel.Visibility = Visibility.Collapsed;
                    _isSync = true;
                    //LblLoginHeader.Text = "synchronizing";
                    LblLoginHeader.Text = "please wait";
                    LblLoginHeader.Margin = new Thickness(0, 0, 0, 0);
                    LblLoginSubHeader.Visibility = Visibility.Visible;
                    //LblLoginSubHeader.Text = "fetching data from new server may take a moment";
                    LblLoginSubHeader.Text = "we're taking care of few things with the new server";

                    GrdMemberUsername.Visibility = Visibility.Collapsed;
                    GrdAdminUsername.Visibility = Visibility.Collapsed;
                    GrdAdminPassword.Visibility = Visibility.Collapsed;
                    PgbLogin.Visibility = Visibility.Visible;
                    TglLoginSwitch.Visibility = Visibility.Collapsed;
                    LblLoginSwitchLable.Visibility = Visibility.Collapsed;
                    BtnLogin.Visibility = Visibility.Collapsed;
                }
                else
                {
                    _isSync = false;

                    if (_isSsessionExpired)
                    {
                        _navigationService.GoBack(Frame);
                        return;
                    }

                    _navigationService.NavigateTo(typeof(MeetingsPage));
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private async Task ChangePasswordUiManip()
        {
            try
            {
                //----------------------------------------------------------------------------------
                //double val = LoginPanel.ActualWidth;
                //Storyboard storyboard = new Storyboard();
                //Duration duration = new Duration(TimeSpan.FromMilliseconds(animeTime));
                //CubicEase ease = new CubicEase { EasingMode = EasingMode.EaseOut };

                //DoubleAnimation animation = new DoubleAnimation();
                //animation.EasingFunction = ease;
                //animation.Duration = duration;
                //storyboard.Children.Add(animation);
                //animation.From = 0;
                //animation.To = val;
                //animation.EnableDependentAnimation = true;
                //Storyboard.SetTarget(animation, ChangePasswordPanel);
                //Storyboard.SetTargetProperty(animation, "(ColumnDefinition.MaxWidth)");
                //storyboard.Begin();
                //----------------------------------------------------------------------------------

                LoginPanel.Visibility = Visibility.Collapsed;
                ChangePasswordPanel.Visibility = Visibility.Visible;

                var polText =
                    await
                        _authService.GetSettingValueBySettingName(DatabaseType.UserDb,
                            ApplicationConstants.UserDbSettingNames.PasswordPolicyText);
                LblChangePasswordSubHeader.Visibility = Visibility.Visible;

                if (polText == null)
                    return;

                var pol = polText.ToString().Replace("<br/>", "\n");
                pol = pol.Replace("; ", "\n");
                LblChangePasswordSubHeader.Text = pol;

                //lbl_ChangePasswordHeader.Margin = new Thickness(0, 0, 0, 20);
                //lbl_ChangePasswordSubHeader.Margin = new Thickness(0, 0, 0, 40);
                //lbl_ChangePasswordSubHeader.FontSize = 15;  //Display password policy
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void txt_OldPassword_KeyUp(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key != VirtualKey.Enter) return;

            if (!String.IsNullOrWhiteSpace(TxtOldPassword.Password))
            {
                TxtNewPassword.Focus(FocusState.Keyboard);
            }
            if (!String.IsNullOrWhiteSpace(TxtNewPassword.Password))
            {
                TxtConfirmNewPassword.Focus(FocusState.Keyboard);
            }
        }

        private void txt_NewPassword_KeyUp(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key != VirtualKey.Enter) return;

            if (!String.IsNullOrWhiteSpace(TxtNewPassword.Password))
            {
                TxtConfirmNewPassword.Focus(FocusState.Keyboard);
            }
        }

        private async void txt_ConfirmNewPassword_KeyUp(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key == VirtualKey.Enter)
            {
                await ChangePasswordCommon();
            }
        }

        private async void btn_ChangePassword_Click(object sender, RoutedEventArgs e)
        {
            var isException = false;
            try
            {
                await ChangePasswordCommon();
            }
            catch (Exception)
            {
                isException = true;
                //_dialogService.ShowMessage("Message:" + ew.Message + "\nInnerException:" + ew.InnerException + "\nStackTrace:" + ew.StackTrace);
            }
            if (!isException) return;
            PgbLogin.Visibility = Visibility.Collapsed;
            await _dialogService.ShowMessage("Change password general error encountered");
        }

        private async Task ChangePasswordCommon()
        {
            try
            {
                DecoyControl.Focus(FocusState.Programmatic);
                BtnChangePassword.IsEnabled = false;

                var rslt = await ChangePasswordProcess();
                if (rslt)
                {
                    _isSync = false;

                    if (_isSsessionExpired)
                    {
                        _navigationService.GoBack(Frame);
                        return;
                    }

                    _navigationService.NavigateTo(typeof(MeetingsPage));
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                BtnChangePassword.IsEnabled = true;
            }
        }

        private async Task<bool> ChangePasswordProcess()
        {
            try
            {
                var logOnModel = (LogOnModel)DataContext;

                if ((String.IsNullOrWhiteSpace(logOnModel.OldPassword)) &&
                    (String.IsNullOrWhiteSpace(logOnModel.NewPassword)) &&
                    (String.IsNullOrWhiteSpace(logOnModel.ConfirmNewPassword)))
                {
                    await _dialogService.ShowMessage("Password fields cannot be empty");
                    TxtOldPassword.Focus(FocusState.Keyboard);
                    return false;
                }

                if (String.IsNullOrWhiteSpace(logOnModel.OldPassword))
                {
                    await _dialogService.ShowMessage("Old password cannot be empty");
                    TxtOldPassword.Focus(FocusState.Keyboard);
                    return false;
                }

                if (String.IsNullOrWhiteSpace(logOnModel.NewPassword))
                {
                    await _dialogService.ShowMessage("New password cannot be empty");
                    TxtNewPassword.Focus(FocusState.Keyboard);
                    return false;
                }

                if (String.IsNullOrWhiteSpace(logOnModel.ConfirmNewPassword))
                {
                    await _dialogService.ShowMessage("Confirm new password cannot be empty");
                    TxtConfirmNewPassword.Focus(FocusState.Keyboard);
                    return false;
                }

                if (!logOnModel.NewPassword.Equals(logOnModel.ConfirmNewPassword))
                {
                    await _dialogService.ShowMessage("New password and confirm new password does not match");
                    return false;
                }

                PgbChangePassword.Visibility = Visibility.Visible;
                var rdm = await _authService.ChangePassword(logOnModel);

                PgbChangePassword.Visibility = Visibility.Collapsed;
                if (!rdm.IsError) return true;
                await _dialogService.ShowMessage(rdm.ErrorMessage);
                return false;

                //If "IsError" false means "ErrorMessage" contains success message
            }
            catch (Exception)
            {
                return false;
            }
        }

        /*private void BtnChangeUser_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                _navigationService.NavigateTo(typeof(LoginPage));
            }
            catch (Exception)
            {
            }
        }*/

        private async void BtnGoOnline_Click(object sender, RoutedEventArgs e)
        {
            await GoOnlineCommon();
        }

        private async Task GoOnlineCommon()
        {
            try
            {
                BtnGoOnline.Content = "Trying online mode...";
                PgbOnlineLogin.Visibility = Visibility.Visible;
                BtnGoOnline.IsEnabled = false;

                for (int i = 0; i < 3; i++)
                {
                    var isSvrUp = await NetworkConnectivityManager.ServerUpCheckOnce();
                    if (isSvrUp)
                    {
                        if (_isSsessionExpired)
                        {
                            Global.UserForceWentOffline = false;
                            _navigationService.NavigateTo(typeof(LoginPage), ErrorCode.Err110);  //try reloading the page for effect on the ui
                        }
                        else
                            _navigationService.NavigateTo(typeof(LoginPage));  //try reloading the page for effect on the ui
                        break;
                    }
                    await Task.Delay(1000);
                }

                BtnGoOnline.Content = "Click here to try online login";
                PgbOnlineLogin.Visibility = Visibility.Collapsed;
                if (!Global.IsOnline)
                    await _dialogService.ShowMessage("Still offline, Please check your connectivity");
            }
            catch (Exception)
            {
            }
            finally
            {
                BtnGoOnline.Content = "Click here to try online login";
                PgbOnlineLogin.Visibility = Visibility.Collapsed;
                BtnGoOnline.IsEnabled = true;
            }
        }

        private void pageRoot_Unloaded(object sender, RoutedEventArgs e)
        {
            /*_navigationService = null;
            _appSettingsManager = null;
            _dialogService = null;
            _authService = null;
            _initService = null;*/
        }


    }
}